/*
 * @(#)PrintPDFReportServlet.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.dms.web;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.apps.Driver;
import org.apache.fop.apps.FOPException;
import org.apache.fop.messaging.MessageHandler;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import com.dcivision.dms.bean.DmsEmailAuditTrail;
import com.dcivision.dms.core.DmsEmailAuditTrailManager;
import com.dcivision.dms.core.FileDownloader;
import com.dcivision.dms.dao.DmsEmailAuditTrailDAObject;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.DataSourceFactory;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;

/**
 * @author           barbin
 * @company          DCIVision Limited
 * @creation date    2006/9/26
 * @version          $Revision: 1.4.2.1 $
 */
public class PrintPDFReportServlet extends HttpServlet {
  
  protected Log log = LogFactory.getLog(this.getClass().getName());
  protected static final String TABLE_LINE = "--------------------------------------------------------------------------------------------------------------";
  String appBase = SystemParameterFactory.getSystemParameter(SystemParameterConstant.APPLICATION_BASE_URL);
  DmsEmailAuditTrailDAObject emailDAO;
  SessionContainer sessionContainer;
  Connection conn = null;
  
  /****************************
   * 1. parse the arguments from page transaction
   * 2. convert argument to array. and put array per value to emailAuditTrail.
   * 3. get result list from core
   * Main function : this class generate the pdf file for download the email audit trail records
   */
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    sessionContainer = (SessionContainer)request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
    String xslPath = null;
    try {
      String outputFileName = null;
      conn = DataSourceFactory.getConnection();
      String requestURL = request.getRequestURL().toString();
      emailDAO = new DmsEmailAuditTrailDAObject(sessionContainer,conn);
      DmsEmailAuditTrail emailAuditTrail = new DmsEmailAuditTrail();
      
      //1.
      String argsArray = request.getParameter("argsArray");
      String[] args = TextUtility.splitString(argsArray,"|");
    	emailAuditTrail.setOperation(args[0]);
    	emailAuditTrail.setOperationSearchType(args[1]);
    	emailAuditTrail.setUserid(TextUtility.parseIntegerObj(args[2]));
    	emailAuditTrail.setUserSearchType(args[3]);
    	emailAuditTrail.setEmailFrom(args[4]);
    	emailAuditTrail.setFromSearchType(args[5]);
    	emailAuditTrail.setEmailTo(args[6]);
    	emailAuditTrail.setToSearchType(args[7]);
    	emailAuditTrail.setEmailCc(args[8]);
    	emailAuditTrail.setCcSearchType(args[9]);
    	emailAuditTrail.setEmailBcc(args[10]);
    	emailAuditTrail.setBccSearchType(args[11]);
    	emailAuditTrail.setEmailSubject(args[12]);
    	emailAuditTrail.setSubjectSearchType(args[13]);
    	emailAuditTrail.setAttchName(args[14]);
    	emailAuditTrail.setAttchNameSearchType(args[15]);
    	emailAuditTrail.setEmailType(args[16]);
    	emailAuditTrail.setTypeSearchType(args[17]);
    	emailAuditTrail.setSentDate(args[18]);
    	emailAuditTrail.setSentDateSearchType(args[19]);
    	emailAuditTrail.setSentDateValue(args[20]);
    	emailAuditTrail.setSecondDate(args[21]);
    	emailAuditTrail.setSecondDateSearchType(args[22]);
    	emailAuditTrail.setSecondDateValue(args[23]);
    	emailAuditTrail.setSortAttribute(args[24]);
    	emailAuditTrail.setSortOrder(args[25]);
    	//emailAuditTrail.setCurStartRowNo("1");
      //2.
      String transactionDate = Utility.getCurrentTimestamp().toString();
      String branchCode = request.getParameter("branchCode");
      //3.
      //Setup assign the xsl
      xslPath = requestURL.substring(0,requestURL.indexOf(request.getContextPath()))+request.getContextPath()+"/jsp/dms/emailAuditTrailReport.xsl";
      outputFileName = "emailAuditTrail_print_" +  String.valueOf(System.currentTimeMillis()) + ".pdf";     
      String xmlStr = this.getReportXMLStr(transactionDate,branchCode,emailAuditTrail);
      this.opXslToPdf(xslPath,xmlStr,outputFileName, request, response);

    } catch (Exception e) {
      log.fatal(e.getMessage(), e);
    }
    {
      try { conn.close(); } catch (Exception ignore) {} finally { conn = null; }
    }
  }
  
  /***********************
   * download the pdf file
   * @param xslPath
   * @param xmlFileStr
   * @param outPutPDFFileName
   * @param request
   * @param response
   * @throws ApplicationException
   * @throws IOException
   * @throws FOPException
   * @throws TransformerException
   */
  private void opXslToPdf(String xslPath, String xmlFileStr, String outPutPDFFileName, HttpServletRequest request, HttpServletResponse response) throws ApplicationException, IOException, FOPException, TransformerException{
    InputStream xslInputStream = getXSLAsInputStream(xslPath);
    byte pdf[] = convertPDFAsByteArray(xmlFileStr, xslInputStream);
    InputStream fileInputStream = new ByteArrayInputStream(pdf);
    String contentType = "application/pdf";
    if (contentType != null) {
      FileDownloader fd = new FileDownloader();
      fd.setFileName(outPutPDFFileName);
      fd.setIsDownload(true);
      fd.setContentType(contentType);
      fd.setInputStream(fileInputStream);
      fd.setRequest(request);
      fd.setResponse(response);
      fd.operate();
    }
  }
  
  /****************************
   * the xsl file inputStream
   * @param xslPath
   * @return
   * @throws MalformedURLException
   * @throws IOException
   */
  
  private InputStream getXSLAsInputStream(String xslPath) throws MalformedURLException, IOException {
    
    //URL xslURL = new URL (appBase+"/jsp/customize/workflow/citic_check_list_form.xsl");
    URL xslURL = new URL (xslPath);
    URLConnection xslConn = xslURL.openConnection();
    return xslConn.getInputStream();
  }
  
  /*******************************
   * generate the pdf file. and get the pdf file byteArrayOutputStream
   * @param xml
   * @param xsl
   * @return
   * @throws IOException
   * @throws FOPException
   * @throws TransformerException
   */
  private byte[] convertPDFAsByteArray(String xml, InputStream xsl) throws IOException, FOPException, TransformerException {
    // Construct driver
    Driver driver = new Driver();
    // Setup logger
    Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
    driver.setLogger(logger);
    MessageHandler.setScreenLogger(logger);
    // Setup Renderer (output format)
    driver.setRenderer(Driver.RENDER_PDF);
    // Setup output
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
      driver.setOutputStream(out);
      // Setup XSLT
      TransformerFactory factory = TransformerFactory.newInstance();
      Transformer transformer = factory.newTransformer(new StreamSource(xsl));
      // Setup input for XSLT transformation
      Source src = new StreamSource(new StringReader(xml));
      // Resulting SAX events (the generated FO) must be piped through to FOP
      Result res = new SAXResult(driver.getContentHandler());
      // Start XSLT transformation and FOP processing
      transformer.transform(src, res);
    } finally {
      out.close();
    }
    return out.toByteArray();
  }
  
  /************************
   * get the String value 
   * @param transactionDate
   * @param branchCode
   * @param dmsEmailAuditTrail
   * @return
   */
  private String getReportXMLStr(String transactionDate,String branchCode,DmsEmailAuditTrail dmsEmailAuditTrail){
    String outStr="";
    try{      
     DmsEmailAuditTrailManager dmsEmailAuditTrailManager = new DmsEmailAuditTrailManager(sessionContainer,conn);
     List outList = new ArrayList();    
     List list = dmsEmailAuditTrailManager.getPDFDefaultList(dmsEmailAuditTrail) ;    
      
      for(int i=0;i<list.size();i++){
      	DmsEmailAuditTrail emailAuditTrail = (DmsEmailAuditTrail)list.get(i);
        outList.add(emailAuditTrail);
      }
      //get the xml by list data
      outStr =  getFormatXmlAsReport(outList,branchCode,"Email Audit Trail List",transactionDate);
    }catch(Exception e){
      log.error(e, e);
    }      
    return outStr;
  }
  
  /*****************
   * 
   * @param elementName
   * @param content
   * @param parent
   */
  protected void createElement(String elementName, String content, Element parent) {
    // Only create the element if the element name is not empty or null
    if (!StringUtils.isEmpty(elementName)) {
      // Create a new element
      Element tmpElement = new Element(elementName);
      tmpElement.setText(content);
      parent.addContent(tmpElement);
    }
  }
  
  /**
  *
  * @param sessionContainer
  * @param conn
  * @param currentProgress
  * @return the xml file name
  */
 public String getFormatXmlAsReport(List reportList,String branchCode,String branchName,String transactionDate) throws ApplicationException, IOException {    
   Writer stringWriter = new StringWriter();
   
   //create pdf form elements and add value;
   Element EmailAuditTrailCheckList = new Element("EmailAuditTrail");
   Element member = new Element("MEMBER");
   //Add the contains into the Root Node
   EmailAuditTrailCheckList.addContent(member);
   
   //The line seperator
   createElement("TABLE_LINE",TABLE_LINE,member);
   // deal with index or modify;
   Element inputStatus = new Element("INPUT_STATUS");
   
   createElement("INPUT_STATUS","COMPLETED",member);
   createElement("OTT_OR_OCH","OCH",member);
   
   createElement("BRANCHCODE",branchCode,member);    
   createElement("BRANCHNAME",branchName,member);
   createElement("DATE", ((transactionDate!=null && transactionDate.length()>10)?transactionDate.substring(0, 10):transactionDate), member);
   
   
   //create a new GregorianCalendar and prepare the simple Date format object
   GregorianCalendar now = new GregorianCalendar();
   SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
   createElement("CURRENT_TIME",sdf.format(now.getTime()),member);
   
   if(!Utility.isEmpty(reportList)){
     for(int i=0 ;i<reportList.size() ;i++){
    	 
       DmsEmailAuditTrail emailTrail = (DmsEmailAuditTrail)reportList.get(i);
       Element reportRecord = new Element("REPORT_RECORD");
       member.addContent(reportRecord);
       createElement("EmailType",emailTrail.getEmailType(),reportRecord);
       createElement("Operation",emailTrail.getOperation(),reportRecord);
       createElement("User",emailTrail.getUserName(),reportRecord);
       createElement("From",Utility.isEmpty(emailTrail.getEmailFrom())?"":parseChar(emailTrail.getEmailFrom()),reportRecord);
       createElement("To",Utility.isEmpty(emailTrail.getEmailTo())?"":parseChar(emailTrail.getEmailTo()),reportRecord);          
       createElement("Cc",Utility.isEmpty(emailTrail.getEmailCc())?"":parseChar(emailTrail.getEmailCc()),reportRecord); 
       createElement("Bcc",Utility.isEmpty(emailTrail.getEmailBcc())?"":parseChar(emailTrail.getEmailBcc()),reportRecord);
       createElement("Subject",Utility.isEmpty(emailTrail.getEmailSubject())?"":parseChar(emailTrail.getEmailSubject()),reportRecord);
       createElement("SentDateTime",Utility.isEmpty(emailTrail.getSentDate())?" \n":emailTrail.getSentDate().toString(),reportRecord);
       createElement("DocumentAttched",Utility.isEmpty(emailTrail.getAttchName())?"":parseChar(emailTrail.getAttchName()),reportRecord);
     }
   }        
   Document document = new Document(EmailAuditTrailCheckList);
   Format format = Format.getRawFormat();
   format.setEncoding("UTF-8");
   format.setIndent("   ");
   XMLOutputter out = new XMLOutputter(format);
   try {
     out.output(document, stringWriter);
   } catch (IOException ioe) {
     log.debug("Error generating XML: ", ioe);
     throw ioe;
   }     
   
   
   //log.info("#### THe XML for Report1 is " + stringWriter.toString());
   return stringWriter.toString();
 }  
 
 /**********************
  * parse the per cell value . if it length more than 25. and do follow it
  * @param str
  * @return sb.toString()
  */
 
 private String parseChar(String str){
	 StringBuffer sb = new StringBuffer();
	 if(str.length()>25){
		 while(str.length()>25){
			 sb.append(str.substring(0,25)+"\n");
			 str = str.substring(25);
		 }
		 sb.append(str);
	 }else{
		 sb.append(str);
	 }
	 return sb.toString();
 }
 
}